package top.dancun.easuser.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import top.dancun.common.entity.RoleEntity;
import top.dancun.common.utils.PageUtils;
import top.dancun.common.utils.Query;
import top.dancun.easuser.dao.RoleDao;
import top.dancun.easuser.dao.RoleMenuDao;
import top.dancun.easuser.dao.UserRoleDao;
import top.dancun.easuser.entity.RoleMenuEntity;
import top.dancun.easuser.entity.UserRoleEntity;
import top.dancun.easuser.service.RoleService;

import java.util.List;
import java.util.Map;
import java.util.Objects;


@Service("roleService")
public class RoleServiceImpl extends ServiceImpl<RoleDao, RoleEntity> implements RoleService {

    @Autowired
    RoleMenuDao roleMenuDao;

    @Autowired
    private DataSourceTransactionManager transactionManager;

    @Autowired
    private UserRoleDao userRoleDao;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        LambdaQueryWrapper<RoleEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(Objects.nonNull(params.get("name")) && !params.get("name").equals(""),RoleEntity::getRoleName,params.get("name"));
        IPage<RoleEntity> page = this.page(
                new Query<RoleEntity>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);
    }

    @Override
    public RoleEntity selectById(Long roleId) {
        RoleEntity role = this.getById(roleId);
        role.getMenuIdList().addAll(roleMenuDao.getMenuIdByRoleId(roleId));


        return role;
    }

    @Override
    @Transactional
    public void saveRoleAndMenu(RoleEntity role) {

        TransactionStatus status =  getTransactionStatus("saveRoleAndMenu");
        try{
            //插入用户数据和菜单数据,出现错误回滚
            this.save(role);
//            List<RoleMenuEntity> roleMenus = new ArrayList<>();
//            for(Long meuiId :role.getMenuIdList()){
//                RoleMenuEntity roleMenu = new RoleMenuEntity();
//                roleMenu.setRoleId(role.getRoleId());
//                roleMenu.setMenuId(meuiId);
//                roleMenus.add(roleMenu);
//            }
            roleMenuDao.insertAll(role.getRoleId(),role.getMenuIdList());
        }catch (Exception sqlError){
            transactionManager.rollback(status);
            throw sqlError;
        }

    }

    @Override
    @Transactional
    public void updateRoleAndMenu(RoleEntity role) {
        TransactionStatus status =  getTransactionStatus("updateRoleAndMenu");
        try{
            //修改用户数据  >> 删除角色相关的角色菜单数据 >> 插艾儒角色菜单 ,出现错误回滚
            this.updateById(role);

            LambdaQueryWrapper<RoleMenuEntity> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(RoleMenuEntity::getRoleId,role.getRoleId());
            roleMenuDao.delete(wrapper);
            roleMenuDao.insertAll(role.getRoleId(),role.getMenuIdList());
        }catch (Exception sqlError){
            transactionManager.rollback(status);
            throw sqlError;
        }

    }

    @Override
    @Transactional
    public void deleteRoleAndMenu(RoleEntity role) {
        TransactionStatus status =  getTransactionStatus("deleteRoleAndMenu");
        try{
            //修改用户数据  >> 删除角色相关的角色菜单数据 >> 插艾儒角色菜单 ,出现错误回滚
            LambdaQueryWrapper<RoleEntity> roleWrapper = Wrappers.lambdaQuery();
            roleWrapper.eq(RoleEntity::getRoleId,role.getRoleId());
            this.remove(roleWrapper);

            LambdaQueryWrapper<RoleMenuEntity> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(RoleMenuEntity::getRoleId,role.getRoleId());
            roleMenuDao.delete(wrapper);

            //删除用户的此角色
            LambdaQueryWrapper<UserRoleEntity> userRolewrapper = Wrappers.lambdaQuery();
            wrapper.eq(RoleMenuEntity::getRoleId,role.getRoleId());
            userRoleDao.delete(userRolewrapper);
        }catch (Exception sqlError){
            transactionManager.rollback(status);
            throw sqlError;
        }

    }

    /**
     * 批量删除角色
     * @param roleIds 角色id列表
     */
    @Transactional
    @Override
    public void deleteAllRole(List<Long> roleIds) {
        TransactionStatus status =  getTransactionStatus("deleteAllRole");
        try{
            //修改用户数据  >> 删除角色相关的角色菜单数据 >> 插艾儒角色菜单 ,出现错误回滚
            LambdaQueryWrapper<RoleEntity> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.in(RoleEntity::getRoleId,roleIds);
            this.remove(queryWrapper);

            LambdaQueryWrapper<RoleMenuEntity> wrapper = Wrappers.lambdaQuery();
            wrapper.in(RoleMenuEntity::getRoleId,roleIds);
            roleMenuDao.delete(wrapper);
        }catch (Exception sqlError){
            transactionManager.rollback(status);
            throw sqlError;
        }
    }

    private TransactionStatus getTransactionStatus(String name){
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        // explicitly setting the transaction name is something that can only be done programmatically
        def.setName(name);
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        TransactionStatus status = transactionManager.getTransaction(def);
        return status;
    }


}